<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<HTML>
<HEAD>
<LINK REL=STYLESHEET TYPE="text/css" HREF="../../stylesheet.css" TITLE="Style">
<META NAME="GENERATOR" CONTENT="Java2HTML Version 1.5">
<TITLE>czestmyr.jjsched.CommandParser (Java2HTML)</TITLE>
</HEAD>
<BODY><TABLE id="Header" border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td colspan="2" width="33%">&nbsp;</td>
<td align="center" colspan="2" width="33%">
<font size="4">CommandParser.java</font>
</td>
<td align="right" colspan="2" width="33%">&nbsp;</td>
</tr>
</TABLE>
<pre ID="Classes">
<A NAME="1"></A><FONT ID="MultiLineComment">/*  This file is a part of JJSched source code
<A NAME="2"></A>    JJSched - Java Jabber Scheduler - a simple Jabber scheduling application
<A NAME="3"></A>    Copyright (C) 2008 Cestmir "CZestmyr" Houska
<A NAME="4"></A>
<A NAME="5"></A>    This program is free software: you can redistribute it and/or modify
<A NAME="6"></A>    it under the terms of the GNU General Public License as published by
<A NAME="7"></A>    the Free Software Foundation, either version 3 of the License, or
<A NAME="8"></A>    (at your option) any later version.
<A NAME="9"></A>
<A NAME="10"></A>    This program is distributed in the hope that it will be useful,
<A NAME="11"></A>    but WITHOUT ANY WARRANTY; without even the implied warranty of
<A NAME="12"></A>    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
<A NAME="13"></A>    GNU General Public License for more details.
<A NAME="14"></A>
<A NAME="15"></A>    You should have received a copy of the GNU General Public License
<A NAME="16"></A>    along with this program.  If not, see &lt;http://www.gnu.org/licenses/&gt; */</FONT>
<A NAME="17"></A>
<A NAME="18"></A><FONT ID="Package">package</FONT> czestmyr.jjsched;
<A NAME="19"></A>
<A NAME="20"></A><FONT ID="Import">import</FONT> java.lang.*;
<A NAME="21"></A><FONT ID="Import">import</FONT> java.util.*;
<A NAME="22"></A>
<A NAME="23"></A><FONT ID="Import">import</FONT> java.nio.charset.*;
<A NAME="24"></A>
<A NAME="25"></A><FONT ID="Import">import</FONT> org.jivesoftware.smack.util.*;
<A NAME="26"></A>
<A NAME="27"></A>enum Token {
<A NAME="28"></A>    REGISTER, UNREGISTER, PING, ECHO, LIST, TIME, PLAN, OFFSET, SETOFFSET, GROUP,
<A NAME="29"></A>    SUBSCRIBE, UNSUBSCRIBE, ADMIN, ME, USERS, ADMINS, MACROS, GROUPS, EVENTS, AT, DESCRIPTION,
<A NAME="30"></A>    USER, ADD, NUMBER, MODIFY, NAME, SELF_SUBSCRIPTION, TRUE, FALSE, LISTUSERS,
<A NAME="31"></A>    LISTEVENTS, PRIVILEGES, REMOVE, QUIT, HELP, INVALID;
<A NAME="32"></A>}
<A NAME="33"></A>
<A NAME="34"></A><FONT ID="FormalComment">/**
<A NAME="35"></A> * Parser of the commands written to the commandline or sent via XMPP.
<A NAME="36"></A> */</FONT>
<A NAME="37"></A><FONT ID="Public">public</FONT> <FONT ID="Class">class</FONT> CommandParser {
<A NAME="38"></A>    <FONT ID="FormalComment">/**
<A NAME="39"></A>     * Constructor.
<A NAME="40"></A>     *
<A NAME="41"></A>     * Initializes the trie with all possible commands
<A NAME="42"></A>     */</FONT>
<A NAME="43"></A>    CommandParser(<A HREF="../../czestmyr/jjsched/DatabaseConnector.java.html">DatabaseConnector</A> dbc, <A HREF="../../czestmyr/jjsched/Config.java.html">Config</A> theConfig, <A HREF="../../czestmyr/jjsched/Macros.java.html">Macros</A> ms, <A HREF="../../czestmyr/jjsched/TimeHandler.java.html">TimeHandler</A> time) {
<A NAME="44"></A>        commands = <FONT ID="New">new</FONT> <A HREF="../../czestmyr/jjsched/StringMatcher.java.html">StringMatcher</A>&lt;Token&gt;();
<A NAME="45"></A>
<A NAME="46"></A>        commands.addMatch(Token.REGISTER,   <FONT ID="StringLiteral">"register"</FONT>);
<A NAME="47"></A>        commands.addMatch(Token.UNREGISTER, <FONT ID="StringLiteral">"unregister"</FONT>);
<A NAME="48"></A>        commands.addMatch(Token.PING,       <FONT ID="StringLiteral">"ping"</FONT>);
<A NAME="49"></A>        commands.addMatch(Token.ECHO,       <FONT ID="StringLiteral">"echo"</FONT>);
<A NAME="50"></A>        commands.addMatch(Token.LIST,       <FONT ID="StringLiteral">"list"</FONT>);
<A NAME="51"></A>        commands.addMatch(Token.TIME,       <FONT ID="StringLiteral">"time"</FONT>);
<A NAME="52"></A>        commands.addMatch(Token.PLAN,       <FONT ID="StringLiteral">"plan"</FONT>);
<A NAME="53"></A>        commands.addMatch(Token.OFFSET,     <FONT ID="StringLiteral">"offset"</FONT>);
<A NAME="54"></A>        commands.addMatch(Token.SETOFFSET,  <FONT ID="StringLiteral">"setoffset"</FONT>);
<A NAME="55"></A>        commands.addMatch(Token.GROUP,      <FONT ID="StringLiteral">"group"</FONT>);
<A NAME="56"></A>        commands.addMatch(Token.SUBSCRIBE,  <FONT ID="StringLiteral">"subscribe"</FONT>);
<A NAME="57"></A>        commands.addMatch(Token.UNSUBSCRIBE,<FONT ID="StringLiteral">"unsubscribe"</FONT>);
<A NAME="58"></A>        commands.addMatch(Token.ADMIN,      <FONT ID="StringLiteral">"admin"</FONT>);
<A NAME="59"></A>        commands.addMatch(Token.ME,         <FONT ID="StringLiteral">"me"</FONT>);
<A NAME="60"></A>        commands.addMatch(Token.USERS,      <FONT ID="StringLiteral">"users"</FONT>);
<A NAME="61"></A>        commands.addMatch(Token.ADMINS,     <FONT ID="StringLiteral">"admins"</FONT>);
<A NAME="62"></A>        commands.addMatch(Token.MACROS,     <FONT ID="StringLiteral">"macros"</FONT>);
<A NAME="63"></A>        commands.addMatch(Token.GROUPS,     <FONT ID="StringLiteral">"groups"</FONT>);
<A NAME="64"></A>        commands.addMatch(Token.EVENTS,     <FONT ID="StringLiteral">"events"</FONT>);
<A NAME="65"></A>        commands.addMatch(Token.AT,         <FONT ID="StringLiteral">"at"</FONT>);
<A NAME="66"></A>        commands.addMatch(Token.DESCRIPTION,<FONT ID="StringLiteral">"description"</FONT>);
<A NAME="67"></A>        commands.addMatch(Token.USER,       <FONT ID="StringLiteral">"user"</FONT>);
<A NAME="68"></A>        commands.addMatch(Token.ADD,        <FONT ID="StringLiteral">"add"</FONT>);
<A NAME="69"></A>        commands.addMatch(Token.NUMBER,     <FONT ID="StringLiteral">"number"</FONT>);
<A NAME="70"></A>        commands.addMatch(Token.MODIFY,     <FONT ID="StringLiteral">"modify"</FONT>);
<A NAME="71"></A>        commands.addMatch(Token.NAME,       <FONT ID="StringLiteral">"name"</FONT>);
<A NAME="72"></A>        commands.addMatch(Token.SELF_SUBSCRIPTION,      <FONT ID="StringLiteral">"selfsubscription"</FONT>);
<A NAME="73"></A>        commands.addMatch(Token.TRUE,       <FONT ID="StringLiteral">"true"</FONT>);
<A NAME="74"></A>        commands.addMatch(Token.FALSE,      <FONT ID="StringLiteral">"false"</FONT>);
<A NAME="75"></A>        commands.addMatch(Token.LISTUSERS,  <FONT ID="StringLiteral">"listusers"</FONT>);
<A NAME="76"></A>        commands.addMatch(Token.LISTEVENTS, <FONT ID="StringLiteral">"listevents"</FONT>);
<A NAME="77"></A>        commands.addMatch(Token.PRIVILEGES, <FONT ID="StringLiteral">"privileges"</FONT>);
<A NAME="78"></A>        commands.addMatch(Token.REMOVE,     <FONT ID="StringLiteral">"remove"</FONT>);
<A NAME="79"></A>        commands.addMatch(Token.QUIT,       <FONT ID="StringLiteral">"quit"</FONT>);
<A NAME="80"></A>        commands.addMatch(Token.HELP,       <FONT ID="StringLiteral">"help"</FONT>);
<A NAME="81"></A>
<A NAME="82"></A>        theDBConnector = dbc;
<A NAME="83"></A>        theMacros = ms;
<A NAME="84"></A>        theTime = time;
<A NAME="85"></A>
<A NAME="86"></A>        ucr = theConfig.getInt(<FONT ID="StringLiteral">"UsersCanRegister"</FONT>).intValue() == <FONT ID="IntegerLiteral">1</FONT>;
<A NAME="87"></A>    }
<A NAME="88"></A>
<A NAME="89"></A>    <FONT ID="FormalComment">/**
<A NAME="90"></A>     * Creates a new action that sends an error string to the user
<A NAME="91"></A>     */</FONT>
<A NAME="92"></A>    <FONT ID="Protected">protected</FONT> <A HREF="../../czestmyr/jjsched/Action.java.html">Action</A> error(String errorString, String user) {
<A NAME="93"></A>        <A HREF="../../czestmyr/jjsched/Action.java.html">Action</A> ret = <FONT ID="New">new</FONT> <A HREF="../../czestmyr/jjsched/Action.java.html">Action</A>(ActionId.ERROR);
<A NAME="94"></A>        ret.sParam1 = errorString;
<A NAME="95"></A>        ret.user = user;
<A NAME="96"></A>        <FONT ID="Return">return</FONT> ret;
<A NAME="97"></A>    }
<A NAME="98"></A>
<A NAME="99"></A>    <FONT ID="FormalComment">/**
<A NAME="100"></A>     * Creates a new action that sends a message to a user
<A NAME="101"></A>     */</FONT>
<A NAME="102"></A>    <FONT ID="Protected">protected</FONT> <A HREF="../../czestmyr/jjsched/Action.java.html">Action</A> message(String msgString, String user) {
<A NAME="103"></A>        <A HREF="../../czestmyr/jjsched/Action.java.html">Action</A> ret = <FONT ID="New">new</FONT> <A HREF="../../czestmyr/jjsched/Action.java.html">Action</A>(ActionId.MESSAGE);
<A NAME="104"></A>        ret.sParam1 = msgString;
<A NAME="105"></A>        ret.user = user;
<A NAME="106"></A>        <FONT ID="Return">return</FONT> ret;
<A NAME="107"></A>    }
<A NAME="108"></A>
<A NAME="109"></A>    <FONT ID="FormalComment">/**
<A NAME="110"></A>     * Parses the string and returns a token that represents it
<A NAME="111"></A>     */</FONT>
<A NAME="112"></A>    <FONT ID="Protected">protected</FONT> Token tokenize(String str) {
<A NAME="113"></A>        Token ret = (Token)commands.match(str);
<A NAME="114"></A>        <FONT ID="If">if</FONT> (ret == <FONT ID="Null">null</FONT>) <FONT ID="Return">return</FONT> Token.INVALID;
<A NAME="115"></A>        <FONT ID="Else">else</FONT> <FONT ID="Return">return</FONT> ret;
<A NAME="116"></A>    }
<A NAME="117"></A>
<A NAME="118"></A>    <FONT ID="FormalComment">/**
<A NAME="119"></A>     * Parses a list of string tokens and decides which action should be taken.
<A NAME="120"></A>     *
<A NAME="121"></A>     * This method is thread-safe. It had to be synchronized because some of its help values reside
<A NAME="122"></A>     * in the class itself as members.
<A NAME="123"></A>     *
<A NAME="124"></A>     * @param   tokens          List of strings to process
<A NAME="125"></A>     * @param   unescapedUser   Jabber id of the sending user as it originally came in the packet
<A NAME="126"></A>     * @param   user            Escaped jabber id (i.e. SQL injections safe)
<A NAME="127"></A>     */</FONT>
<A NAME="128"></A>    <FONT ID="Synchronized">synchronized</FONT> <FONT ID="Public">public</FONT> <A HREF="../../czestmyr/jjsched/Action.java.html">Action</A> parse(LinkedList&lt;String&gt; tokens, String unescapedUser, String user) {
<A NAME="129"></A>        <FONT ID="Int">int</FONT> tokensSize = tokens.size();
<A NAME="130"></A>
<A NAME="131"></A>        <FONT ID="If">if</FONT> (tokensSize == <FONT ID="IntegerLiteral">0</FONT>) <FONT ID="Return">return</FONT> error(<FONT ID="StringLiteral">"No command provided"</FONT>, user);
<A NAME="132"></A>
<A NAME="133"></A>        <FONT ID="SingleLineComment">////////////////////////////////////////
<A NAME="134"></A></FONT>        <FONT ID="SingleLineComment">//                                    //
<A NAME="135"></A></FONT>        <FONT ID="SingleLineComment">// Find out what the user wants to do //
<A NAME="136"></A></FONT>        <FONT ID="SingleLineComment">//                                    //
<A NAME="137"></A></FONT>        <FONT ID="SingleLineComment">////////////////////////////////////////
<A NAME="138"></A></FONT>
<A NAME="139"></A>        <A HREF="../../czestmyr/jjsched/Action.java.html">Action</A> action = <FONT ID="New">new</FONT> <A HREF="../../czestmyr/jjsched/Action.java.html">Action</A>(ActionId.NONE);
<A NAME="140"></A>        action.user = user;
<A NAME="141"></A>
<A NAME="142"></A>        <FONT ID="SingleLineComment">// If the user is not registered, don't let the parsing continue (only for registration)
<A NAME="143"></A></FONT>        <FONT ID="If">if</FONT> (!theDBConnector.isRegisteredUser(user)) {
<A NAME="144"></A>            <FONT ID="If">if</FONT> (tokenize(tokens.get(<FONT ID="IntegerLiteral">0</FONT>)) != Token.REGISTER) {
<A NAME="145"></A>                <FONT ID="Return">return</FONT> action;
<A NAME="146"></A>            }
<A NAME="147"></A>        }
<A NAME="148"></A>
<A NAME="149"></A>        <FONT ID="SingleLineComment">// Get the first token and build the corresponding action
<A NAME="150"></A></FONT>        <FONT ID="Switch">switch</FONT>(tokenize(tokens.get(<FONT ID="IntegerLiteral">0</FONT>))) {
<A NAME="151"></A>            <FONT ID="Case">case</FONT> HELP:
<A NAME="152"></A>                <FONT ID="SingleLineComment">//Generic help
<A NAME="153"></A></FONT>                <FONT ID="If">if</FONT> (tokens.size() == <FONT ID="IntegerLiteral">1</FONT>) {
<A NAME="154"></A>                    action = message(Help.getBasicHelp(), user);
<A NAME="155"></A>                <FONT ID="SingleLineComment">//Command help
<A NAME="156"></A></FONT>                } <FONT ID="Else">else</FONT> {
<A NAME="157"></A>                    action = message(Help.getTopicHelp(tokens.get(<FONT ID="IntegerLiteral">1</FONT>)), user);
<A NAME="158"></A>                }
<A NAME="159"></A>            <FONT ID="Break">break</FONT>;
<A NAME="160"></A>            <FONT ID="Case">case</FONT> PING:
<A NAME="161"></A>                action = <FONT ID="New">new</FONT> <A HREF="../../czestmyr/jjsched/Action.java.html">Action</A>(ActionId.ECHO);
<A NAME="162"></A>                action.sParam1 = <FONT ID="StringLiteral">"A ping message just for you!"</FONT>;
<A NAME="163"></A>            <FONT ID="Break">break</FONT>;
<A NAME="164"></A>            <FONT ID="Case">case</FONT> ECHO:
<A NAME="165"></A>                StringBuilder sb = <FONT ID="New">new</FONT> StringBuilder(<FONT ID="StringLiteral">"=&gt; "</FONT>);
<A NAME="166"></A>                ListIterator it2 = tokens.listIterator(<FONT ID="IntegerLiteral">1</FONT>);
<A NAME="167"></A>                <FONT ID="While">while</FONT> (it2.hasNext()){
<A NAME="168"></A>                    sb.append(<FONT ID="StringLiteral">"\""</FONT>);
<A NAME="169"></A>                    sb.append((String)it2.next());
<A NAME="170"></A>                    sb.append(<FONT ID="StringLiteral">"\" "</FONT>);
<A NAME="171"></A>                }
<A NAME="172"></A>                action = <FONT ID="New">new</FONT> <A HREF="../../czestmyr/jjsched/Action.java.html">Action</A>(ActionId.ECHO);
<A NAME="173"></A>                action.sParam1 = sb.toString();
<A NAME="174"></A>            <FONT ID="Break">break</FONT>;
<A NAME="175"></A>            <FONT ID="Case">case</FONT> REGISTER:
<A NAME="176"></A>                <FONT ID="If">if</FONT> (tokensSize == <FONT ID="IntegerLiteral">2</FONT>) {
<A NAME="177"></A>                    token1 = tokenize(tokens.get(<FONT ID="IntegerLiteral">1</FONT>));
<A NAME="178"></A>                    <FONT ID="SingleLineComment">//The user wants to register himself and the server allows it
<A NAME="179"></A></FONT>                    <FONT ID="If">if</FONT> (token1 == Token.ME &amp;&amp; ucr){
<A NAME="180"></A>                        <FONT ID="SingleLineComment">//We allow this only if the user is not registered yet
<A NAME="181"></A></FONT>                        <FONT ID="If">if</FONT> (!theDBConnector.isRegisteredUser(user)){
<A NAME="182"></A>                            action = <FONT ID="New">new</FONT> <A HREF="../../czestmyr/jjsched/Action.java.html">Action</A>(ActionId.REGISTER);
<A NAME="183"></A>                    action.otherUser = user;
<A NAME="184"></A>                        } <FONT ID="Else">else</FONT> action = message(<FONT ID="StringLiteral">"You are registered already."</FONT>, user);
<A NAME="185"></A>                    <FONT ID="SingleLineComment">//The user wants to register someone else and is admin
<A NAME="186"></A></FONT>                    } <FONT ID="Else">else</FONT> <FONT ID="If">if</FONT> (theDBConnector.adminCanModifyUsers(user)) {
<A NAME="187"></A>                        action = <FONT ID="New">new</FONT> <A HREF="../../czestmyr/jjsched/Action.java.html">Action</A>(ActionId.REGISTER);
<A NAME="188"></A>                        <FONT ID="If">if</FONT> (token1 == Token.ME) {
<A NAME="189"></A>                            action.otherUser = user;
<A NAME="190"></A>                        } <FONT ID="Else">else</FONT> {
<A NAME="191"></A>                            action.otherUser = StringParser.escapeJID(tokens.get(<FONT ID="IntegerLiteral">1</FONT>));
<A NAME="192"></A>                        }
<A NAME="193"></A>                        <FONT ID="SingleLineComment">//Check, whether the user in question is not registered
<A NAME="194"></A></FONT>                        <FONT ID="If">if</FONT> (!theDBConnector.isRegisteredUser(action.otherUser)) {
<A NAME="195"></A>                            <FONT ID="SingleLineComment">//Check validity of JID
<A NAME="196"></A></FONT>                            <FONT ID="If">if</FONT> ((StringUtils.parseName(action.otherUser) == <FONT ID="StringLiteral">""</FONT> ||
<A NAME="197"></A>                                StringUtils.parseServer(action.otherUser) == <FONT ID="StringLiteral">""</FONT>) &amp;&amp;
<A NAME="198"></A>                                !action.otherUser.equals(<FONT ID="StringLiteral">"console"</FONT>)) {
<A NAME="199"></A>                                action = message(action.otherUser + <FONT ID="StringLiteral">" is not a valid JID."</FONT>, user);
<A NAME="200"></A>                            }
<A NAME="201"></A>                        } <FONT ID="Else">else</FONT> action = message(<FONT ID="StringLiteral">"User "</FONT> + action.otherUser + <FONT ID="StringLiteral">" is registered already."</FONT>, user);
<A NAME="202"></A>                    } <FONT ID="Else">else</FONT> <FONT ID="If">if</FONT> (token1 == Token.ME) {
<A NAME="203"></A>                        action = message(<FONT ID="StringLiteral">"This server does not allow ordinary users registering themselves."</FONT>, user);
<A NAME="204"></A>                    } <FONT ID="Else">else</FONT> action = message(<FONT ID="StringLiteral">"You don't have the privilege to register other people."</FONT>, user);
<A NAME="205"></A>                } <FONT ID="Else">else</FONT> action = error(<FONT ID="StringLiteral">"Unknown command or bad syntax"</FONT>, user);
<A NAME="206"></A>            <FONT ID="Break">break</FONT>;
<A NAME="207"></A>            <FONT ID="Case">case</FONT> UNREGISTER:
<A NAME="208"></A>                <FONT ID="If">if</FONT> (tokensSize == <FONT ID="IntegerLiteral">2</FONT>){
<A NAME="209"></A>                    token1 = tokenize(tokens.get(<FONT ID="IntegerLiteral">1</FONT>));
<A NAME="210"></A>                    <FONT ID="SingleLineComment">//The user wants to unregister himself
<A NAME="211"></A></FONT>                    <FONT ID="If">if</FONT> (token1 == Token.ME){
<A NAME="212"></A>                        <FONT ID="SingleLineComment">//We allow this only if the user is not registered yet
<A NAME="213"></A></FONT>                        <FONT ID="If">if</FONT> (theDBConnector.isRegisteredUser(user)){
<A NAME="214"></A>                            action = <FONT ID="New">new</FONT> <A HREF="../../czestmyr/jjsched/Action.java.html">Action</A>(ActionId.UNREGISTER);
<A NAME="215"></A>                            action.otherUser = user;
<A NAME="216"></A>                        } <FONT ID="Else">else</FONT> action = message(<FONT ID="StringLiteral">"You are not registered."</FONT>, user);
<A NAME="217"></A>                    <FONT ID="SingleLineComment">//The user wants to unregister someone else and is admin
<A NAME="218"></A></FONT>                    } <FONT ID="Else">else</FONT> <FONT ID="If">if</FONT> (theDBConnector.adminCanModifyUsers(user)) {
<A NAME="219"></A>                        action.otherUser = StringParser.escapeJID(tokens.get(<FONT ID="IntegerLiteral">1</FONT>));
<A NAME="220"></A>                        <FONT ID="SingleLineComment">//Check that the user in question is registered
<A NAME="221"></A></FONT>                        <FONT ID="If">if</FONT> (theDBConnector.isRegisteredUser(action.otherUser)) {
<A NAME="222"></A>                            action.id = ActionId.UNREGISTER;
<A NAME="223"></A>                        } <FONT ID="Else">else</FONT> action = message(<FONT ID="StringLiteral">"User "</FONT> + action.otherUser + <FONT ID="StringLiteral">" is not registered."</FONT>, user);
<A NAME="224"></A>                    } <FONT ID="Else">else</FONT> action = message(<FONT ID="StringLiteral">"You don't have the privilege to unregister other people."</FONT>, user);
<A NAME="225"></A>                } <FONT ID="Else">else</FONT> action = error(<FONT ID="StringLiteral">"Unknown command or bad syntax"</FONT>, user);
<A NAME="226"></A>            <FONT ID="Break">break</FONT>;
<A NAME="227"></A>            <FONT ID="Case">case</FONT> LIST:
<A NAME="228"></A>                <FONT ID="If">if</FONT> (tokensSize == <FONT ID="IntegerLiteral">2</FONT>){
<A NAME="229"></A>                    token1 = tokenize(tokens.get(<FONT ID="IntegerLiteral">1</FONT>));
<A NAME="230"></A>                    <FONT ID="Switch">switch</FONT> (token1) {
<A NAME="231"></A>                    <FONT ID="Case">case</FONT> USERS:
<A NAME="232"></A>                        <FONT ID="If">if</FONT> (theDBConnector.adminCanModifyUsers(user)){
<A NAME="233"></A>                            action = <FONT ID="New">new</FONT> <A HREF="../../czestmyr/jjsched/Action.java.html">Action</A>(ActionId.LIST_USERS);
<A NAME="234"></A>                        } <FONT ID="Else">else</FONT> action = message(<FONT ID="StringLiteral">"You don't have the privilege to list users"</FONT>, user);
<A NAME="235"></A>                    <FONT ID="Break">break</FONT>;
<A NAME="236"></A>                    <FONT ID="Case">case</FONT> ADMINS:
<A NAME="237"></A>                        <FONT ID="If">if</FONT> (theDBConnector.adminCanModifyAdmins(user)){
<A NAME="238"></A>                            action.id = ActionId.LIST_ADMINS;
<A NAME="239"></A>                        } <FONT ID="Else">else</FONT> action = message(<FONT ID="StringLiteral">"You don't have the privilege to list admins"</FONT>, user);
<A NAME="240"></A>                    <FONT ID="Break">break</FONT>;
<A NAME="241"></A>                    <FONT ID="Case">case</FONT> MACROS:
<A NAME="242"></A>                        Iterator macroit = theMacros.getMacrosIterator();
<A NAME="243"></A>                        action.id = ActionId.MESSAGE;
<A NAME="244"></A>                        action.sParam1 = <FONT ID="StringLiteral">"Currently defined macros and their substitutions:\n"</FONT>;
<A NAME="245"></A>                        <FONT ID="While">while</FONT> (macroit.hasNext()){
<A NAME="246"></A>                            Map.Entry&lt;String, Vector&lt;String&gt;&gt; macro = (Map.Entry&lt;String, Vector&lt;String&gt;&gt;)macroit.next();
<A NAME="247"></A>                            action.sParam1 += <FONT ID="StringLiteral">"\""</FONT> + macro.getKey() + <FONT ID="StringLiteral">"\" =&gt; "</FONT>;
<A NAME="248"></A>                            Iterator substit = ((Vector&lt;String&gt;)macro.getValue()).iterator();
<A NAME="249"></A>                            <FONT ID="While">while</FONT> (substit.hasNext()){
<A NAME="250"></A>                                action.sParam1 += <FONT ID="StringLiteral">"\""</FONT> + substit.next() + <FONT ID="StringLiteral">"\" "</FONT>;
<A NAME="251"></A>                            }
<A NAME="252"></A>                            action.sParam1 += <FONT ID="StringLiteral">"\n"</FONT>;
<A NAME="253"></A>                        }
<A NAME="254"></A>                    <FONT ID="Break">break</FONT>;
<A NAME="255"></A>                    <FONT ID="Case">case</FONT> GROUPS:
<A NAME="256"></A>                        <FONT ID="SingleLineComment">//Check that the user can modify groups
<A NAME="257"></A></FONT>                        <FONT ID="If">if</FONT> (theDBConnector.adminCanModifyGroups(user)){
<A NAME="258"></A>                            action.id = ActionId.LIST_GROUPS;
<A NAME="259"></A>                        } <FONT ID="Else">else</FONT> {
<A NAME="260"></A>                            action = message(<FONT ID="StringLiteral">"You don't have the privilege to list groups"</FONT>, user);
<A NAME="261"></A>                        }
<A NAME="262"></A>                    <FONT ID="Break">break</FONT>;
<A NAME="263"></A>                    <FONT ID="Case">case</FONT> EVENTS:
<A NAME="264"></A>                        action.id = ActionId.LIST_EVENTS;
<A NAME="265"></A>                        action.user = user;
<A NAME="266"></A>                    <FONT ID="Break">break</FONT>;
<A NAME="267"></A>                    <FONT ID="Default">default</FONT>:
<A NAME="268"></A>                        action = message(<FONT ID="StringLiteral">"Invalid list entity. See 'help list' for valid list entities."</FONT>, user);
<A NAME="269"></A>                    <FONT ID="Break">break</FONT>;
<A NAME="270"></A>                    }
<A NAME="271"></A>                } <FONT ID="Else">else</FONT> action = error(<FONT ID="StringLiteral">"Unknown command or bad syntax"</FONT>, user);
<A NAME="272"></A>            <FONT ID="Break">break</FONT>;
<A NAME="273"></A>            <FONT ID="Case">case</FONT> TIME:
<A NAME="274"></A>                <FONT ID="If">if</FONT> (tokensSize &gt;= <FONT ID="IntegerLiteral">1</FONT>){
<A NAME="275"></A>                    <FONT ID="SingleLineComment">//A user has requested to view the server time
<A NAME="276"></A></FONT>                    <FONT ID="If">if</FONT> (tokensSize == <FONT ID="IntegerLiteral">1</FONT>) {
<A NAME="277"></A>                        action = message(theTime.getFormattedTime(), user);
<A NAME="278"></A>                    } <FONT ID="Else">else</FONT> <FONT ID="If">if</FONT> (tokensSize == <FONT ID="IntegerLiteral">2</FONT>){
<A NAME="279"></A>                        token1 = tokenize(tokens.get(<FONT ID="IntegerLiteral">1</FONT>));
<A NAME="280"></A>                        <FONT ID="SingleLineComment">//A user has requested to show his time
<A NAME="281"></A></FONT>                        <FONT ID="If">if</FONT> (token1 == Token.ME){
<A NAME="282"></A>                            action = message(theTime.getFormattedTime(theTime.getLongTime()+theDBConnector.getUserTimeOffset(user)), user);
<A NAME="283"></A>                        <FONT ID="SingleLineComment">//An admin has requested to show a time of another user
<A NAME="284"></A></FONT>                        } <FONT ID="Else">else</FONT> <FONT ID="If">if</FONT> (theDBConnector.adminCanModifyUsers(user)){
<A NAME="285"></A>                            action.otherUser = StringParser.escapeJID(tokens.get(<FONT ID="IntegerLiteral">1</FONT>));
<A NAME="286"></A>                            <FONT ID="If">if</FONT> (theDBConnector.isRegisteredUser(action.otherUser)){
<A NAME="287"></A>                                action = message(theTime.getFormattedTime(theTime.getLongTime() 
<A NAME="288"></A>                                                                        + theDBConnector.getUserTimeOffset(action.otherUser)), user);
<A NAME="289"></A>                            } <FONT ID="Else">else</FONT> action = message(<FONT ID="StringLiteral">"User "</FONT>+tokens.get(<FONT ID="IntegerLiteral">1</FONT>)+<FONT ID="StringLiteral">" is not a registered user"</FONT>, user);
<A NAME="290"></A>                        } <FONT ID="Else">else</FONT> action = message(<FONT ID="StringLiteral">"You don't have the rights to view other user's information"</FONT>, user);
<A NAME="291"></A>                    } <FONT ID="Else">else</FONT> action = message(<FONT ID="StringLiteral">"Invalid number of arguments for 'time'. See 'help time' for more info."</FONT>, user);
<A NAME="292"></A>                } <FONT ID="Else">else</FONT> action = error(<FONT ID="StringLiteral">"Unknown command or bad syntax"</FONT>, user);
<A NAME="293"></A>            <FONT ID="Break">break</FONT>;
<A NAME="294"></A>            <FONT ID="Case">case</FONT> PLAN:
<A NAME="295"></A>            <FONT ID="If">if</FONT> (tokensSize &gt;= <FONT ID="IntegerLiteral">1</FONT>) {
<A NAME="296"></A>                <FONT ID="Boolean">boolean</FONT> commandIsExpected = <FONT ID="True">true</FONT>;
<A NAME="297"></A>                <FONT ID="Boolean">boolean</FONT> validPlan = <FONT ID="True">true</FONT>;
<A NAME="298"></A>
<A NAME="299"></A>                <FONT ID="SingleLineComment">//Prepare the plan struct
<A NAME="300"></A></FONT>                action.plan.singleuser = <FONT ID="True">true</FONT>;
<A NAME="301"></A>                action.plan.timestamp = <FONT ID="IntegerLiteral">0</FONT>;
<A NAME="302"></A>                action.plan.username = <FONT ID="Null">null</FONT>;
<A NAME="303"></A>                action.plan.description = <FONT ID="Null">null</FONT>;
<A NAME="304"></A>
<A NAME="305"></A>                PlanCommand cmd = PlanCommand.NONE;
<A NAME="306"></A>                <FONT ID="For">for</FONT> (<FONT ID="Int">int</FONT> i = <FONT ID="IntegerLiteral">1</FONT>; i &lt; tokens.size(); ++i){
<A NAME="307"></A>                <FONT ID="If">if</FONT> (commandIsExpected) {
<A NAME="308"></A>                    token1 = tokenize(tokens.get(i));
<A NAME="309"></A>                    <FONT ID="If">if</FONT> (token1 == Token.AT){
<A NAME="310"></A>                        cmd = PlanCommand.AT;
<A NAME="311"></A>                    } <FONT ID="Else">else</FONT> <FONT ID="If">if</FONT> (token1 == Token.DESCRIPTION) {
<A NAME="312"></A>                        cmd = PlanCommand.DESCRIPTION;
<A NAME="313"></A>                    } <FONT ID="Else">else</FONT> <FONT ID="If">if</FONT> (token1 == Token.USER) {
<A NAME="314"></A>                        cmd = PlanCommand.USER;
<A NAME="315"></A>                    } <FONT ID="Else">else</FONT> <FONT ID="If">if</FONT> (token1 == Token.GROUP){
<A NAME="316"></A>                        cmd = PlanCommand.GROUP;
<A NAME="317"></A>                    } <FONT ID="Else">else</FONT> {
<A NAME="318"></A>                        action = message(<FONT ID="StringLiteral">"Invalid parameter for command plan: "</FONT>+tokens.get(i), user);
<A NAME="319"></A>                        validPlan = <FONT ID="False">false</FONT>;
<A NAME="320"></A>                        <FONT ID="Break">break</FONT>;
<A NAME="321"></A>                    }
<A NAME="322"></A>                } <FONT ID="Else">else</FONT> {
<A NAME="323"></A>                    <FONT ID="Switch">switch</FONT>(cmd) {
<A NAME="324"></A>                        <FONT ID="Case">case</FONT> AT:
<A NAME="325"></A>                            <FONT ID="Try">try</FONT> {
<A NAME="326"></A>                                action.plan.timestamp = theTime.parseToServerTime(tokens.get(i), 
<A NAME="327"></A>                                                                           theDBConnector.getUserTimeOffset(user));
<A NAME="328"></A>                            } <FONT ID="Catch">catch</FONT> (Exception e) {
<A NAME="329"></A>                                action = message(<FONT ID="StringLiteral">"Time expression parse error: "</FONT>+e.getMessage(), user);
<A NAME="330"></A>                                <FONT ID="SingleLineComment">//e.printStackTrace();
<A NAME="331"></A></FONT>                                validPlan = <FONT ID="False">false</FONT>;
<A NAME="332"></A>                            }
<A NAME="333"></A>                        <FONT ID="Break">break</FONT>;
<A NAME="334"></A>                        <FONT ID="Case">case</FONT> DESCRIPTION:
<A NAME="335"></A>                            action.plan.description = tokens.get(i);
<A NAME="336"></A>                        <FONT ID="Break">break</FONT>;
<A NAME="337"></A>                        <FONT ID="Case">case</FONT> USER:
<A NAME="338"></A>                            action.plan.singleuser = <FONT ID="True">true</FONT>;
<A NAME="339"></A>                            <FONT ID="If">if</FONT> (tokenize(tokens.get(i)) == Token.ME){
<A NAME="340"></A>                                action.plan.username = user;
<A NAME="341"></A>                            <FONT ID="SingleLineComment">//You can plan for other users only if you have the privilege to modify users
<A NAME="342"></A></FONT>                            } <FONT ID="Else">else</FONT> <FONT ID="If">if</FONT> (theDBConnector.adminCanModifyUsers(user)) {
<A NAME="343"></A>                                action.plan.username = StringParser.escapeJID(tokens.get(i));
<A NAME="344"></A>                            } <FONT ID="Else">else</FONT> {
<A NAME="345"></A>                                action = message(<FONT ID="StringLiteral">"You cannot plan events for other users, unless you are admin with the"</FONT>
<A NAME="346"></A>                                               + <FONT ID="StringLiteral">" privilege to modify users."</FONT>, user);
<A NAME="347"></A>                                validPlan = <FONT ID="False">false</FONT>;
<A NAME="348"></A>                            }
<A NAME="349"></A>                        <FONT ID="Break">break</FONT>;
<A NAME="350"></A>                        <FONT ID="Case">case</FONT> GROUP:
<A NAME="351"></A>                            <FONT ID="SingleLineComment">//You can plan events for groups only if you have the privilege to modify groups
<A NAME="352"></A></FONT>                            <FONT ID="SingleLineComment">//Or if you are administrator of the given group
<A NAME="353"></A></FONT>                            action.plan.singleuser = <FONT ID="False">false</FONT>;
<A NAME="354"></A>                            <FONT ID="Try">try</FONT> {
<A NAME="355"></A>                                <FONT ID="If">if</FONT> (theDBConnector.adminCanModifyGroups(user) ||
<A NAME="356"></A>                                    theDBConnector.userCanPlanGroup(user, theDBConnector.getGroupID(action.plan.username))) {
<A NAME="357"></A>                                    <FONT ID="If">if</FONT> (tokenize(tokens.get(i)) == Token.NUMBER) {
<A NAME="358"></A>                                        ++i;
<A NAME="359"></A>                                        action.plan.groupId = Integer.parseInt(tokens.get(i));
<A NAME="360"></A>                                    } <FONT ID="Else">else</FONT> {
<A NAME="361"></A>                                        action.plan.groupId = <FONT ID="IntegerLiteral">0</FONT>;
<A NAME="362"></A>                                    }
<A NAME="363"></A>                                } <FONT ID="Else">else</FONT> {
<A NAME="364"></A>                                    action = message(<FONT ID="StringLiteral">"You cannot plan events for groups, unless you are admin with the"</FONT>
<A NAME="365"></A>                                                   + <FONT ID="StringLiteral">" privilege to modify groups or have the privileges to plan for the given group."</FONT>, user);
<A NAME="366"></A>                                    validPlan = <FONT ID="False">false</FONT>;
<A NAME="367"></A>                                }
<A NAME="368"></A>                            } <FONT ID="Catch">catch</FONT> (Exception e) {
<A NAME="369"></A>                                action = message(<FONT ID="StringLiteral">"Could not plan group event - DB error: "</FONT>+e.getMessage(), user);
<A NAME="370"></A>                                validPlan = <FONT ID="False">false</FONT>;
<A NAME="371"></A>                            }
<A NAME="372"></A>                        <FONT ID="Break">break</FONT>;
<A NAME="373"></A>                    }
<A NAME="374"></A>                }
<A NAME="375"></A>                commandIsExpected = !commandIsExpected;
<A NAME="376"></A>                }
<A NAME="377"></A>                <FONT ID="If">if</FONT> (action.plan.timestamp == <FONT ID="IntegerLiteral">0</FONT> &amp;&amp; validPlan) {
<A NAME="378"></A>                    action = message(<FONT ID="StringLiteral">"Missing time specifier in plan command"</FONT>, user);
<A NAME="379"></A>                    validPlan = <FONT ID="False">false</FONT>;
<A NAME="380"></A>                }
<A NAME="381"></A>                <FONT ID="If">if</FONT> (action.plan.username == <FONT ID="Null">null</FONT>) {
<A NAME="382"></A>                    action.plan.username = user;
<A NAME="383"></A>                }
<A NAME="384"></A>                <FONT ID="If">if</FONT> (action.plan.description == <FONT ID="Null">null</FONT>) {
<A NAME="385"></A>                    action.plan.description = <FONT ID="StringLiteral">"You have a plan for now without a description!"</FONT>;
<A NAME="386"></A>                }
<A NAME="387"></A>                <FONT ID="If">if</FONT> (validPlan) action.id = ActionId.PLAN;
<A NAME="388"></A>            } <FONT ID="Else">else</FONT> action = error(<FONT ID="StringLiteral">"Unknown command or bad syntax"</FONT>, user);
<A NAME="389"></A>            <FONT ID="Break">break</FONT>;
<A NAME="390"></A>            <FONT ID="Case">case</FONT> OFFSET:
<A NAME="391"></A>                <FONT ID="If">if</FONT> (tokensSize &gt;= <FONT ID="IntegerLiteral">1</FONT>) {
<A NAME="392"></A>                    <FONT ID="SingleLineComment">//A user is requesting his own offset
<A NAME="393"></A></FONT>                    <FONT ID="If">if</FONT> (tokensSize == <FONT ID="IntegerLiteral">1</FONT>) {
<A NAME="394"></A>                        action = message(theTime.getFormattedOffset(theDBConnector.getUserTimeOffset(user)), user);
<A NAME="395"></A>                    } <FONT ID="Else">else</FONT> <FONT ID="If">if</FONT> (tokensSize == <FONT ID="IntegerLiteral">2</FONT>) {
<A NAME="396"></A>                        token1 = tokenize(tokens.get(<FONT ID="IntegerLiteral">1</FONT>));
<A NAME="397"></A>                        <FONT ID="SingleLineComment">//A user has requested to show his offset
<A NAME="398"></A></FONT>                        <FONT ID="If">if</FONT> (token1 == Token.ME){
<A NAME="399"></A>                            action = message(theTime.getFormattedOffset(theDBConnector.getUserTimeOffset(user)), user);
<A NAME="400"></A>                        }
<A NAME="401"></A>                        <FONT ID="SingleLineComment">//An admin is requesting someone else's offset
<A NAME="402"></A></FONT>                        <FONT ID="Else">else</FONT> <FONT ID="If">if</FONT> (theDBConnector.adminCanModifyUsers(user)){
<A NAME="403"></A>                            action.otherUser = StringParser.escapeJID(tokens.get(<FONT ID="IntegerLiteral">1</FONT>));
<A NAME="404"></A>                            <FONT ID="If">if</FONT> (theDBConnector.isRegisteredUser(action.otherUser)){
<A NAME="405"></A>                                action = message(theTime.getFormattedOffset(theDBConnector.getUserTimeOffset(action.otherUser)), user);
<A NAME="406"></A>                            } <FONT ID="Else">else</FONT> action = message(<FONT ID="StringLiteral">"User "</FONT>+tokens.get(<FONT ID="IntegerLiteral">1</FONT>)+<FONT ID="StringLiteral">" is not a registered user"</FONT>, user);
<A NAME="407"></A>                        } <FONT ID="Else">else</FONT> action = message(<FONT ID="StringLiteral">"You don't have the privilege to modify or view other users' information."</FONT>, user);
<A NAME="408"></A>                    } <FONT ID="Else">else</FONT> action = message(<FONT ID="StringLiteral">"Wrong argument count for 'offset', please refer to 'help offset' for more info."</FONT>, user);
<A NAME="409"></A>                } <FONT ID="Else">else</FONT> action = error(<FONT ID="StringLiteral">"Unknown command or bad syntax"</FONT>, user);
<A NAME="410"></A>            <FONT ID="Break">break</FONT>;
<A NAME="411"></A>            <FONT ID="Case">case</FONT> SETOFFSET:
<A NAME="412"></A>                <FONT ID="If">if</FONT> (tokensSize == <FONT ID="IntegerLiteral">3</FONT>) {      
<A NAME="413"></A>                    <FONT ID="Boolean">boolean</FONT> cont = <FONT ID="True">true</FONT>;
<A NAME="414"></A>                    token1 = tokenize(tokens.get(<FONT ID="IntegerLiteral">1</FONT>));
<A NAME="415"></A>
<A NAME="416"></A>                    <FONT ID="SingleLineComment">//A user sets his own offset
<A NAME="417"></A></FONT>                    <FONT ID="If">if</FONT> (token1 == Token.ME) {
<A NAME="418"></A>                        action.otherUser = user;
<A NAME="419"></A>                    <FONT ID="SingleLineComment">//An admin sets somebody else's offset
<A NAME="420"></A></FONT>                    } <FONT ID="Else">else</FONT> <FONT ID="If">if</FONT> (theDBConnector.adminCanModifyUsers(user)) {
<A NAME="421"></A>                        action.otherUser = StringParser.escapeJID(tokens.get(<FONT ID="IntegerLiteral">1</FONT>));
<A NAME="422"></A>                        <FONT ID="If">if</FONT> (!theDBConnector.isRegisteredUser(action.otherUser)) {
<A NAME="423"></A>                            action = message(<FONT ID="StringLiteral">"The user "</FONT>+tokens.get(<FONT ID="IntegerLiteral">1</FONT>)+<FONT ID="StringLiteral">" is not registered"</FONT>, user);
<A NAME="424"></A>                            cont = <FONT ID="False">false</FONT>;
<A NAME="425"></A>                        }
<A NAME="426"></A>                    <FONT ID="SingleLineComment">//A user tries to set someone else's offset
<A NAME="427"></A></FONT>                    } <FONT ID="Else">else</FONT> {
<A NAME="428"></A>                        action = message(<FONT ID="StringLiteral">"You don't have the privilege to modify users"</FONT>, user);
<A NAME="429"></A>                        cont = <FONT ID="False">false</FONT>;
<A NAME="430"></A>                    }
<A NAME="431"></A>                    <FONT ID="SingleLineComment">//Try to decode the timediff expression
<A NAME="432"></A></FONT>                    <FONT ID="If">if</FONT> (cont) <FONT ID="Try">try</FONT> {
<A NAME="433"></A>                        String td = tokens.get(<FONT ID="IntegerLiteral">2</FONT>);
<A NAME="434"></A>                        <FONT ID="Int">int</FONT> m = td.indexOf(<FONT ID="CharacerLiteral">'-'</FONT>);
<A NAME="435"></A>                        <FONT ID="Int">int</FONT> p = td.indexOf(<FONT ID="CharacerLiteral">'+'</FONT>);
<A NAME="436"></A>                        <FONT ID="If">if</FONT> (p != -<FONT ID="IntegerLiteral">1</FONT> &amp;&amp; m != -<FONT ID="IntegerLiteral">1</FONT>) {
<A NAME="437"></A>                            action = message(<FONT ID="StringLiteral">"You cannot have both '-' and '+' before the timediff expression"</FONT>, user);
<A NAME="438"></A>                            cont = <FONT ID="False">false</FONT>;
<A NAME="439"></A>                        } <FONT ID="Else">else</FONT> <FONT ID="If">if</FONT> (p != -<FONT ID="IntegerLiteral">1</FONT>) {
<A NAME="440"></A>                            action.lParam = (<FONT ID="Int">int</FONT>)theTime.parseTimeDiff(td.substring(p+<FONT ID="IntegerLiteral">1</FONT>));
<A NAME="441"></A>                        } <FONT ID="Else">else</FONT> <FONT ID="If">if</FONT> (m != -<FONT ID="IntegerLiteral">1</FONT>) {
<A NAME="442"></A>                            action.lParam = -(<FONT ID="Int">int</FONT>)theTime.parseTimeDiff(td.substring(m+<FONT ID="IntegerLiteral">1</FONT>));
<A NAME="443"></A>                        } <FONT ID="Else">else</FONT> {
<A NAME="444"></A>                            action.lParam = (<FONT ID="Int">int</FONT>)theTime.parseTimeDiff(td);
<A NAME="445"></A>                        }
<A NAME="446"></A>                    } <FONT ID="Catch">catch</FONT> (Exception e) {
<A NAME="447"></A>                        action = message(e.getMessage(), user);
<A NAME="448"></A>                        cont = <FONT ID="False">false</FONT>;
<A NAME="449"></A>                    }
<A NAME="450"></A>                    <FONT ID="If">if</FONT> (cont) {
<A NAME="451"></A>                        action.id = ActionId.SETOFFSET;
<A NAME="452"></A>                        action.user = user;
<A NAME="453"></A>                    }
<A NAME="454"></A>                } <FONT ID="Else">else</FONT> action = error(<FONT ID="StringLiteral">"Unknown command or bad syntax"</FONT>, user);
<A NAME="455"></A>            <FONT ID="Break">break</FONT>;
<A NAME="456"></A>            <FONT ID="Case">case</FONT> GROUP:
<A NAME="457"></A>                <FONT ID="If">if</FONT> (tokensSize &gt;= <FONT ID="IntegerLiteral">2</FONT>) {
<A NAME="458"></A>                    token1 = tokenize(tokens.get(<FONT ID="IntegerLiteral">1</FONT>));
<A NAME="459"></A>                    <FONT ID="SingleLineComment">//Adding new groups is only for global group admins
<A NAME="460"></A></FONT>                    <FONT ID="If">if</FONT> (token1 == Token.ADD) {
<A NAME="461"></A>                        <FONT ID="If">if</FONT> (tokensSize != <FONT ID="IntegerLiteral">4</FONT>) {
<A NAME="462"></A>                            action = message(<FONT ID="StringLiteral">"Incorect format of group command. See 'help group' for the correct syntax."</FONT>, user);
<A NAME="463"></A>                        } <FONT ID="Else">else</FONT> {
<A NAME="464"></A>                            <FONT ID="If">if</FONT> (!theDBConnector.adminCanModifyGroups(user)){
<A NAME="465"></A>                                action = message(<FONT ID="StringLiteral">"You don't have the privilege to add new groups"</FONT>, user);
<A NAME="466"></A>                            } <FONT ID="Else">else</FONT> {
<A NAME="467"></A>                                action.id = ActionId.GROUP_ADD;
<A NAME="468"></A>                                action.sParam1 = tokens.get(<FONT ID="IntegerLiteral">2</FONT>);
<A NAME="469"></A>                                action.sParam2 = tokens.get(<FONT ID="IntegerLiteral">3</FONT>);
<A NAME="470"></A>                            }
<A NAME="471"></A>                        }
<A NAME="472"></A>                    } <FONT ID="Else">else</FONT> {
<A NAME="473"></A>                    <FONT ID="SingleLineComment">//Variants 2-7 are for global admins or for the specified group admins
<A NAME="474"></A></FONT>                        <FONT ID="SingleLineComment">//Get group identification in case we will need it
<A NAME="475"></A></FONT>                        <FONT ID="SingleLineComment">//Try block is necessary here in case number conversion or DB access fails
<A NAME="476"></A></FONT>                        <FONT ID="Try">try</FONT> {
<A NAME="477"></A>                            <FONT ID="Boolean">boolean</FONT> groupByName = <FONT ID="False">false</FONT>;
<A NAME="478"></A>                            <FONT ID="If">if</FONT> (tokensSize &gt;= <FONT ID="IntegerLiteral">3</FONT>) {
<A NAME="479"></A>                                <FONT ID="If">if</FONT> (tokenize(tokens.get(<FONT ID="IntegerLiteral">2</FONT>)) == Token.NUMBER) {
<A NAME="480"></A>                                    <FONT ID="If">if</FONT> (tokensSize == <FONT ID="IntegerLiteral">3</FONT>) {
<A NAME="481"></A>                                        action = message(<FONT ID="StringLiteral">"Incorrect group specification. See 'help groupspec' for details."</FONT>, user);
<A NAME="482"></A>                                    } <FONT ID="Else">else</FONT> {
<A NAME="483"></A>                                        groupByName = <FONT ID="False">false</FONT>; <FONT ID="SingleLineComment">//groupID is in tokens.get(3)
<A NAME="484"></A></FONT>                                        action.lParam = Integer.parseInt(tokens.get(<FONT ID="IntegerLiteral">3</FONT>));
<A NAME="485"></A>                                    }
<A NAME="486"></A>                                } <FONT ID="Else">else</FONT> {
<A NAME="487"></A>                                    groupByName = <FONT ID="True">true</FONT>; <FONT ID="SingleLineComment">//Name is always in tokens.get(2)
<A NAME="488"></A></FONT>                                    action.lParam = theDBConnector.getGroupID(tokens.get(<FONT ID="IntegerLiteral">2</FONT>));
<A NAME="489"></A>                                }
<A NAME="490"></A>                            } <FONT ID="Else">else</FONT> {
<A NAME="491"></A>                                action = message(<FONT ID="StringLiteral">"Bad group command syntax"</FONT>, user);
<A NAME="492"></A>                                <FONT ID="Break">break</FONT>;
<A NAME="493"></A>                            }
<A NAME="494"></A>
<A NAME="495"></A>                            <FONT ID="SingleLineComment">//Check permissions
<A NAME="496"></A></FONT>                            <FONT ID="If">if</FONT> (token1 == Token.REMOVE) {
<A NAME="497"></A>                                <FONT ID="If">if</FONT> (!theDBConnector.adminCanModifyGroups(user)) {
<A NAME="498"></A>                                    action = message(<FONT ID="StringLiteral">"You don't have the privilege to modify groups."</FONT>, user);
<A NAME="499"></A>                                    <FONT ID="Break">break</FONT>;
<A NAME="500"></A>                                }
<A NAME="501"></A>                            } <FONT ID="Else">else</FONT> <FONT ID="If">if</FONT> (token1 == Token.MODIFY ||
<A NAME="502"></A>                                token1 == Token.SUBSCRIBE ||
<A NAME="503"></A>                                token1 == Token.UNSUBSCRIBE ||
<A NAME="504"></A>                                token1 == Token.PRIVILEGES) {
<A NAME="505"></A>                                <FONT ID="If">if</FONT> (!theDBConnector.adminCanModifyGroups(user) &amp;&amp;
<A NAME="506"></A>                                    !theDBConnector.userCanModifyGroup(user, action.lParam)) {
<A NAME="507"></A>                                    action = message(<FONT ID="StringLiteral">"You don't have the privilege to modify this group"</FONT>+
<A NAME="508"></A>                                                    <FONT ID="StringLiteral">" (and you cannot modify groups in general)."</FONT>, user);
<A NAME="509"></A>                                    <FONT ID="Break">break</FONT>;
<A NAME="510"></A>                                }
<A NAME="511"></A>                            } <FONT ID="Else">else</FONT> <FONT ID="If">if</FONT> (token1 == Token.LISTUSERS ||
<A NAME="512"></A>                                token1 == Token.LISTEVENTS) {
<A NAME="513"></A>                                <FONT ID="If">if</FONT> (!theDBConnector.adminCanModifyGroups(user) &amp;&amp;
<A NAME="514"></A>                                    !theDBConnector.userCanListGroup(user, action.lParam)) {
<A NAME="515"></A>                                    action = message(<FONT ID="StringLiteral">"You don't have the privilege to list this group"</FONT>+
<A NAME="516"></A>                                                    <FONT ID="StringLiteral">" (and you cannot modify groups in general)."</FONT>, user);
<A NAME="517"></A>                                    <FONT ID="Break">break</FONT>;
<A NAME="518"></A>                                }
<A NAME="519"></A>                            }
<A NAME="520"></A>
<A NAME="521"></A>                                <FONT ID="Int">int</FONT> i = <FONT ID="IntegerLiteral">3</FONT>; <FONT ID="SingleLineComment">//Used to get the correct token
<A NAME="522"></A></FONT>                                <FONT ID="If">if</FONT> (!groupByName) ++i;
<A NAME="523"></A>                                <FONT ID="If">if</FONT> (token1 == Token.MODIFY) {
<A NAME="524"></A>                                    <FONT ID="While">while</FONT> (i &lt; tokensSize) {
<A NAME="525"></A>                                        token2 = tokenize(tokens.get(i));
<A NAME="526"></A>                                        <FONT ID="If">if</FONT> (token2 == Token.DESCRIPTION) {
<A NAME="527"></A>                                            ++i;
<A NAME="528"></A>                                            <FONT ID="If">if</FONT> (i &lt; tokensSize)
<A NAME="529"></A>                                                action.sParam1 = tokens.get(i);
<A NAME="530"></A>                                            <FONT ID="Else">else</FONT> {
<A NAME="531"></A>                                                action = message(<FONT ID="StringLiteral">"No new group description specified in the group command."</FONT>, user);
<A NAME="532"></A>                                            }
<A NAME="533"></A>                                        } <FONT ID="Else">else</FONT> <FONT ID="If">if</FONT> (token2 == Token.NAME) {
<A NAME="534"></A>                                            ++i;
<A NAME="535"></A>                                            <FONT ID="If">if</FONT> (i &lt; tokensSize)
<A NAME="536"></A>                                                action.sParam2 = tokens.get(i);
<A NAME="537"></A>                                            <FONT ID="Else">else</FONT> {
<A NAME="538"></A>                                                action = message(<FONT ID="StringLiteral">"No new group name specified in the group command."</FONT>, user);
<A NAME="539"></A>                                            }
<A NAME="540"></A>                                        } <FONT ID="Else">else</FONT> <FONT ID="If">if</FONT> (token2 == Token.SELF_SUBSCRIPTION) {
<A NAME="541"></A>                                            ++i;
<A NAME="542"></A>                                            <FONT ID="If">if</FONT> (i &lt; tokensSize) {
<A NAME="543"></A>                                                token2 = tokenize(tokens.get(i));
<A NAME="544"></A>                                                <FONT ID="If">if</FONT> (token2 == Token.TRUE)
<A NAME="545"></A>                                                    action.iParam = <FONT ID="IntegerLiteral">1</FONT>;
<A NAME="546"></A>                                                <FONT ID="Else">else</FONT> <FONT ID="If">if</FONT> (token2 == Token.FALSE)
<A NAME="547"></A>                                                    action.iParam = <FONT ID="IntegerLiteral">0</FONT>;
<A NAME="548"></A>                                                <FONT ID="Else">else</FONT> {
<A NAME="549"></A>                                                    action = message(<FONT ID="StringLiteral">"Missing boolean value after \"selfsubscription\"."</FONT>, user);
<A NAME="550"></A>                                                    i = tokensSize; <FONT ID="SingleLineComment">//Break from while statement
<A NAME="551"></A></FONT>                                                }
<A NAME="552"></A>                                            } <FONT ID="Else">else</FONT> {
<A NAME="553"></A>                                                action = message(<FONT ID="StringLiteral">"Missing \"true\" or \"false\" after \"selfsubscription\"."</FONT>, user);
<A NAME="554"></A>                                            }
<A NAME="555"></A>                                        } <FONT ID="Else">else</FONT> {
<A NAME="556"></A>                                            action = message(<FONT ID="StringLiteral">"Incorrect format of group command. See 'help group' for the correct syntax."</FONT>, user);
<A NAME="557"></A>                                            i = tokensSize; <FONT ID="SingleLineComment">//break from the while statement and *hack warning* serve as flag for incorrect parsing
<A NAME="558"></A></FONT>                                        }
<A NAME="559"></A>                                        ++i;
<A NAME="560"></A>                                    }
<A NAME="561"></A>                                    <FONT ID="If">if</FONT> (i == tokensSize) <FONT ID="SingleLineComment">//i serves as a flag for correct group statement here
<A NAME="562"></A></FONT>                                        action.id = ActionId.GROUP_MODIFY;
<A NAME="563"></A>                                } <FONT ID="Else">else</FONT> <FONT ID="If">if</FONT> (token1 == Token.LISTUSERS) {
<A NAME="564"></A>                                    <FONT ID="If">if</FONT> (tokensSize != i) <FONT ID="SingleLineComment">// i should equal the correct number of tokens in this command - 3 or 4
<A NAME="565"></A></FONT>                                        action = message(<FONT ID="StringLiteral">"Incorrect format of group command. See 'help group' for the correct syntax."</FONT>, user);
<A NAME="566"></A>                                    <FONT ID="Else">else</FONT>
<A NAME="567"></A>                                        action.id = ActionId.GROUP_LISTUSERS;
<A NAME="568"></A>                                } <FONT ID="Else">else</FONT> <FONT ID="If">if</FONT> (token1 == Token.SUBSCRIBE) {
<A NAME="569"></A>                                    <FONT ID="If">if</FONT> (tokensSize != i+<FONT ID="IntegerLiteral">1</FONT>) <FONT ID="SingleLineComment">// i+1 should equal the correct number of tokens in this command - 4 or 5
<A NAME="570"></A></FONT>                                        action = message(<FONT ID="StringLiteral">"Incorrect format of group command. See 'help group' for the correct syntax."</FONT>, user);
<A NAME="571"></A>                                    <FONT ID="Else">else</FONT> {
<A NAME="572"></A>                                        action.otherUser = StringParser.escapeJID(tokens.get(i));
<A NAME="573"></A>                                        action.id = ActionId.GROUP_SUBSCRIBE;
<A NAME="574"></A>                                    } <FONT ID="SingleLineComment">//--------------------------------------------------------
<A NAME="575"></A></FONT>                                } <FONT ID="Else">else</FONT> <FONT ID="If">if</FONT> (token1 == Token.UNSUBSCRIBE) {
<A NAME="576"></A>                                    <FONT ID="If">if</FONT> (tokensSize != i+<FONT ID="IntegerLiteral">1</FONT>)
<A NAME="577"></A>                                        action = message(<FONT ID="StringLiteral">"Incorrect format of group command. See 'help group' for the correct syntax."</FONT>, user);
<A NAME="578"></A>                                    <FONT ID="Else">else</FONT> {
<A NAME="579"></A>                                        action.otherUser = StringParser.escapeJID(tokens.get(i));
<A NAME="580"></A>                                        action.id = ActionId.GROUP_UNSUBSCRIBE;
<A NAME="581"></A>                                    }
<A NAME="582"></A>                                } <FONT ID="Else">else</FONT> <FONT ID="If">if</FONT> (token1 == Token.PRIVILEGES) {
<A NAME="583"></A>                                    <FONT ID="If">if</FONT> (tokensSize != i+<FONT ID="IntegerLiteral">2</FONT>)
<A NAME="584"></A>                                        action = message(<FONT ID="StringLiteral">"Incorrect format of group command. See 'help group' for the correct syntax."</FONT>, user);
<A NAME="585"></A>                                    <FONT ID="Else">else</FONT> {
<A NAME="586"></A>                                        action.otherUser = StringParser.escapeJID(tokens.get(i));
<A NAME="587"></A>                                        action.iParam = Integer.parseInt(tokens.get(i+<FONT ID="IntegerLiteral">1</FONT>));
<A NAME="588"></A>                                        action.id = ActionId.GROUP_PRIVILEGES;
<A NAME="589"></A>                                    }
<A NAME="590"></A>                                } <FONT ID="Else">else</FONT> <FONT ID="If">if</FONT> (token1 == Token.REMOVE) {
<A NAME="591"></A>                                    <FONT ID="If">if</FONT> (tokensSize != i)
<A NAME="592"></A>                                        action = message(<FONT ID="StringLiteral">"Incorrect format of group command. See 'help group' for the correct syntax."</FONT>, user);
<A NAME="593"></A>                                    <FONT ID="Else">else</FONT> {
<A NAME="594"></A>                                        action.id = ActionId.GROUP_REMOVE;
<A NAME="595"></A>                                    }
<A NAME="596"></A>                                } <FONT ID="Else">else</FONT> <FONT ID="If">if</FONT> (token1 == Token.LISTEVENTS) {
<A NAME="597"></A>                                    <FONT ID="If">if</FONT> (tokensSize != i)    
<A NAME="598"></A>                                        action = message(<FONT ID="StringLiteral">"Incorrect format of group command. See 'help group' for the correct syntax."</FONT>, user);
<A NAME="599"></A>                                    <FONT ID="Else">else</FONT> {
<A NAME="600"></A>                                        action.id = ActionId.GROUP_LISTEVENTS;
<A NAME="601"></A>                                    }
<A NAME="602"></A>                                } <FONT ID="Else">else</FONT> {
<A NAME="603"></A>                                    action = message(<FONT ID="StringLiteral">"Unrecognized group command. See 'help group' for more details"</FONT>, user);
<A NAME="604"></A>                                }
<A NAME="605"></A>                        } <FONT ID="Catch">catch</FONT> (Exception e) {
<A NAME="606"></A>                            action = message(e.getMessage(), user);
<A NAME="607"></A>                        }
<A NAME="608"></A>                    }
<A NAME="609"></A>                } <FONT ID="Else">else</FONT> action = error(<FONT ID="StringLiteral">"Unknown command or bad syntax"</FONT>, user);
<A NAME="610"></A>            <FONT ID="Break">break</FONT>;
<A NAME="611"></A>            <FONT ID="Case">case</FONT> SUBSCRIBE:
<A NAME="612"></A>                <FONT ID="If">if</FONT> (tokensSize == <FONT ID="IntegerLiteral">2</FONT>) {
<A NAME="613"></A>                    <FONT ID="SingleLineComment">//Check if ordinary users can subscribe to group
<A NAME="614"></A></FONT>                    <FONT ID="Try">try</FONT> {
<A NAME="615"></A>                        <FONT ID="SingleLineComment">//Get group ID
<A NAME="616"></A></FONT>                        action.lParam = theDBConnector.getGroupID(tokens.get(<FONT ID="IntegerLiteral">1</FONT>));
<A NAME="617"></A>                        <FONT ID="SingleLineComment">//Check if users can subscribe to the group
<A NAME="618"></A></FONT>                        <FONT ID="If">if</FONT> (theDBConnector.usersCanSubscribe(action.lParam)) {
<A NAME="619"></A>                            action.otherUser = action.user = user;
<A NAME="620"></A>                            action.id = ActionId.GROUP_SUBSCRIBE;
<A NAME="621"></A>                        } <FONT ID="Else">else</FONT> action = message(<FONT ID="StringLiteral">"Sorry, ordinary users cannot subscribe to this group. "</FONT>+
<A NAME="622"></A>                                                <FONT ID="StringLiteral">"Contact group admin for subscription."</FONT>, user);
<A NAME="623"></A>                    } <FONT ID="Catch">catch</FONT> (Exception e) {
<A NAME="624"></A>                        action = message(e.getMessage(), user);
<A NAME="625"></A>                    }
<A NAME="626"></A>                } <FONT ID="Else">else</FONT> action = error(<FONT ID="StringLiteral">"Unknown command or bad syntax"</FONT>, user);
<A NAME="627"></A>            <FONT ID="Break">break</FONT>;
<A NAME="628"></A>            <FONT ID="Case">case</FONT> UNSUBSCRIBE:
<A NAME="629"></A>                <FONT ID="If">if</FONT> (tokensSize == <FONT ID="IntegerLiteral">2</FONT>) {
<A NAME="630"></A>                    <FONT ID="SingleLineComment">//Check if ordinary users can subscribe to group
<A NAME="631"></A></FONT>                    <FONT ID="Try">try</FONT> {
<A NAME="632"></A>                        <FONT ID="SingleLineComment">//Get group ID
<A NAME="633"></A></FONT>                        action.lParam = theDBConnector.getGroupID(tokens.get(<FONT ID="IntegerLiteral">1</FONT>));
<A NAME="634"></A>                        action.id = ActionId.GROUP_UNSUBSCRIBE;
<A NAME="635"></A>                        action.otherUser = action.user = user;
<A NAME="636"></A>                    } <FONT ID="Catch">catch</FONT> (Exception e) {
<A NAME="637"></A>                        action = message(e.getMessage(), user);
<A NAME="638"></A>                    }
<A NAME="639"></A>                } <FONT ID="Else">else</FONT> action = error(<FONT ID="StringLiteral">"Unknown command or bad syntax"</FONT>, user);
<A NAME="640"></A>            <FONT ID="Break">break</FONT>;
<A NAME="641"></A>            <FONT ID="Case">case</FONT> ADMIN:
<A NAME="642"></A>                <FONT ID="If">if</FONT> (tokensSize == <FONT ID="IntegerLiteral">3</FONT>) {
<A NAME="643"></A>                    <FONT ID="SingleLineComment">//Get the other user's jabber ID
<A NAME="644"></A></FONT>                    action.otherUser = StringParser.escapeJID(tokens.get(<FONT ID="IntegerLiteral">1</FONT>));
<A NAME="645"></A>                    <FONT ID="SingleLineComment">//Check, whether the sending user has the privileges to modify admins
<A NAME="646"></A></FONT>                    <FONT ID="If">if</FONT> (!theDBConnector.adminCanModifyAdmins(user))
<A NAME="647"></A>                        action = message(<FONT ID="StringLiteral">"You don't have the privileges to modify admins"</FONT>, user);
<A NAME="648"></A>                    <FONT ID="Else">else</FONT> <FONT ID="Try">try</FONT> {
<A NAME="649"></A>                        action.iParam = Integer.parseInt(tokens.get(<FONT ID="IntegerLiteral">2</FONT>));
<A NAME="650"></A>                        action.user = user;
<A NAME="651"></A>                        <FONT ID="SingleLineComment">//Disallow removing privilege to modify admins from self (ensure at least one admin)
<A NAME="652"></A></FONT>                        <FONT ID="If">if</FONT> (action.iParam%<FONT ID="IntegerLiteral">2</FONT> == <FONT ID="IntegerLiteral">0</FONT> &amp;&amp; user.equals(action.otherUser))
<A NAME="653"></A>                            <FONT ID="Throw">throw</FONT> <FONT ID="New">new</FONT> Exception(<FONT ID="StringLiteral">"Cannot remove admin privileges from self"</FONT>);
<A NAME="654"></A>                        action.id = ActionId.GROUP_ADMIN;
<A NAME="655"></A>                    } <FONT ID="Catch">catch</FONT> (Exception e) {
<A NAME="656"></A>                        action = message(e.getMessage(), user);
<A NAME="657"></A>                    }
<A NAME="658"></A>                } <FONT ID="Else">else</FONT> action = error(<FONT ID="StringLiteral">"Unknown command or bad syntax"</FONT>, user);
<A NAME="659"></A>            <FONT ID="Break">break</FONT>;
<A NAME="660"></A>
<A NAME="661"></A>            <FONT ID="SingleLineComment">//Finally, the possibility to quit jjsched from console and default action - error message
<A NAME="662"></A></FONT>            <FONT ID="Case">case</FONT> QUIT:
<A NAME="663"></A>                <FONT ID="If">if</FONT> (unescapedUser.equals(<FONT ID="StringLiteral">"console"</FONT>)) {
<A NAME="664"></A>                    action = <FONT ID="New">new</FONT> <A HREF="../../czestmyr/jjsched/Action.java.html">Action</A>(ActionId.QUIT);
<A NAME="665"></A>                    <FONT ID="Break">break</FONT>;
<A NAME="666"></A>                }
<A NAME="667"></A>            <FONT ID="Default">default</FONT>:
<A NAME="668"></A>                action = error(<FONT ID="StringLiteral">"Unknown command or bad syntax"</FONT>, user);
<A NAME="669"></A>            <FONT ID="Break">break</FONT>;
<A NAME="670"></A>        }
<A NAME="671"></A>
<A NAME="672"></A>        action.unescapedUser = unescapedUser;
<A NAME="673"></A>        action.user = user;
<A NAME="674"></A>
<A NAME="675"></A>        <FONT ID="Return">return</FONT> action;
<A NAME="676"></A>    }
<A NAME="677"></A>
<A NAME="678"></A>    Token token1;
<A NAME="679"></A>    Token token2;
<A NAME="680"></A>
<A NAME="681"></A>    <FONT ID="Private">private</FONT> <A HREF="../../czestmyr/jjsched/StringMatcher.java.html">StringMatcher</A>&lt;Token&gt; commands;
<A NAME="682"></A>    <FONT ID="Private">private</FONT> <FONT ID="Boolean">boolean</FONT> ucr;
<A NAME="683"></A>
<A NAME="684"></A>    <FONT ID="Private">private</FONT> <A HREF="../../czestmyr/jjsched/DatabaseConnector.java.html">DatabaseConnector</A> theDBConnector;
<A NAME="685"></A>    <FONT ID="Private">private</FONT> <A HREF="../../czestmyr/jjsched/Macros.java.html">Macros</A> theMacros;
<A NAME="686"></A>    <FONT ID="Private">private</FONT> <A HREF="../../czestmyr/jjsched/TimeHandler.java.html">TimeHandler</A> theTime;
<A NAME="687"></A>}
<A NAME="688"></A>
<A NAME="689"></A><FONT ID="FormalComment">/** States of 'plan' command parser */</FONT>
<A NAME="690"></A>enum PlanCommand{
<A NAME="691"></A>    NONE, AT, DESCRIPTION, USER, GROUP
<A NAME="692"></A>}
<A NAME="693"></A></pre>
</BODY>
</HTML>